package com.fingard.dsp.bank.directbank.ccb12;

import cn.ccb.secapi.SecAPI;
import com.fingard.FGBiz;
import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.DirectBase;
import com.fingard.dsp.bank.directbank.ccb12.util.SecurityMessageHeader;
import com.fingard.dsp.bank.directbank.ccb12.util.SecurityMessageHeaderUtils;
import com.fingard.dsp.bank.directbank.ccb12.util.XMLUtils;
import com.fingard.net.WebRequest;
import com.fingard.text.StringHelper;
import com.fingard.xml.XmlTextWriter;
import sun.misc.BASE64Decoder;

import java.io.File;
import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * 建行银保通基础工具类
 * 
 * @author Cruise
 * @date 2019/4/3
 */
public class CCB12Base extends DirectBase {
    private static final String STR_FORMAT = "0000000000";
    public static DecimalFormat decimalFormat = new DecimalFormat(STR_FORMAT);
    public static BASE64Decoder base64Decoder = new BASE64Decoder();
    protected static String strtmpFile = FGBiz.DSPHOME_Parent + File.separator + "config" + File.separator + "portfiles" + File.separator + "CCB12" + File.separator;
    //    protected static byte[] triDesKeys = new byte[1024];//3desKeys;
    private static Date _sessionTime = new Date();
    protected String txCode = "";
    protected String signature = "";
    protected String[] tmpSign = new String[]{"", ""};
    protected String reqSeqID;
    protected String page = "";



    public CCB12Base() {

    }
	protected String getCharset() {
        return getBankConfig().getCharset("UTF-8");
    }
    protected String getQryTransID() {
        Date tmpDateNow = new Date();
        return Format.DateTime17SSSFormat.format(tmpDateNow);
    }
	
	protected void writeCommonHeader(XmlTextWriter xmlWriter,ActSetItem actItem) throws Exception{
	if (StringHelper.isNullOrEmpty(txCode) || StringHelper.isNullOrEmpty(reqSeqID)) {
        throw new Exception("未赋值txCode或reqSeqID");
    }
        Date date = new Date();
        Date tmpDateNow = getDayCutTime(date);
        xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"" + getCharset() + "\"?>");
        xmlWriter.writeStartElement("TX");
        xmlWriter.writeStartElement("TX_HEADER");
        xmlWriter.writeElementString("SYS_HDR_LEN", "0", true);//<TX_HEADER>节点内容的长度（包括节点本身）
        xmlWriter.writeElementString("SYS_PKG_VRSN", "01");
        xmlWriter.writeElementString("SYS_TTL_LEN", "0", true);//从<?xml version="1.0" encoding="UTF-8" ?>到</TX>的长度
        xmlWriter.writeElementString("SYS_REQ_SEC_ID", "105005");
        xmlWriter.writeElementString("SYS_SND_SEC_ID", getBankConfig().getValueAsString("localSecNode"));//服务版本号105005
        xmlWriter.writeElementString("SYS_TX_CODE", txCode);
        xmlWriter.writeElementString("SYS_TX_TYPE", "020000");
        xmlWriter.writeElementString("SYS_TX_VRSN", "01");
        xmlWriter.writeElementString("SYS_EVT_TRACE_ID", getQryTransID()+"00000001");
        xmlWriter.writeElementString("SYS_SND_SERIAL_NO", Format.DateAndHourFormat.format(new Date()));
        xmlWriter.writeElementString("SYS_PKG_TYPE", "1");
        xmlWriter.writeElementString("SYS_MSG_LEN", "0", true);//<TX_BODY>节点内容的长度（包括节点本身）。
        xmlWriter.writeElementString("SYS_IS_ENCRYPTED", "3");
        xmlWriter.writeElementString("SYS_ENCRYPT_TYPE", "3");
        xmlWriter.writeElementString("SYS_COMPRESS_TYPE", "0");
        xmlWriter.writeElementString("SYS_EMB_MSG_LEN", "0");
        xmlWriter.writeElementString("SYS_REQ_TIME", Format.DateTime17SSSFormat.format(date));
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.HOUR, 1);// 24小时制
        date = cal.getTime();
        xmlWriter.writeElementString("SYS_TIME_LEFT", Format.TimeSSFormat.format(date));
        xmlWriter.writeElementString("SYS_PKG_STS_TYPE", "00"); //发起方流水号
        xmlWriter.writeEndElement(); // TX_HEADER
        xmlWriter.writeStartElement("TX_BODY");
        xmlWriter.writeStartElement("COMMON");
        xmlWriter.writeStartElement("FILE_LIST_PACK");
        xmlWriter.writeElementString("FILE_NUM", "0");
        xmlWriter.writeElementString("FILE_MODE", "0");
        xmlWriter.writeElementString("FILE_NODE", "");
        xmlWriter.writeElementString("FILE_NAME_PACK", "");
        xmlWriter.writeElementString("FILE_PATH_PACK", "");
        xmlWriter.writeEndElement();
        xmlWriter.writeEndElement();//COMMON
        xmlWriter.writeStartElement("ENTITY");
        xmlWriter.writeStartElement("COM_ENTITY");
        xmlWriter.writeElementString("Inst_Eng_ShrtNm", "CCB");
        xmlWriter.writeElementString("Ins_Co_ID", actItem.merchantId);
        xmlWriter.writeElementString("Ins_Co_Jrnl_No", reqSeqID);
        xmlWriter.writeElementString("CCBIns_ID", actItem.appId);
        xmlWriter.writeElementString("Ins_Co_Acg_Dt", Format.Date8Format.format(tmpDateNow));
        xmlWriter.writeEndElement();//COM_ENTITY
    }

    protected String sendToBank(String p_reqStr) throws Exception {
        boolean signCd = getBankConfig().getValueAsBool("signCd");
        byte[] sign = new byte[0];
        String localSecNode = getBankConfig().getValueAsString("localSecNode");
        SecAPI.nodeInit(localSecNode);
        if(signCd){
            sign = SecAPI.genSign(localSecNode, p_reqStr.getBytes());
            WriteBankLogLn2("客户端对报文签名:" + sign.length + " " + new String(sign));
        }
        // 生成安全头
        SecurityMessageHeader securityMessageHeader =
                new SecurityMessageHeader();
        securityMessageHeader.setServiceId(XMLUtils.getElementText(p_reqStr,
                "SYS_TX_CODE"));
        securityMessageHeader.setServiceType(XMLUtils.getElementText(
                p_reqStr, "SYS_TX_TYPE"));
        String evtTraceId =
                XMLUtils.getElementText(p_reqStr, "SYS_EVT_TRACE_ID");
        securityMessageHeader.setEvtTraceId(evtTraceId);
        securityMessageHeader.setSign(new String(sign));
        securityMessageHeader.setSecNodeId(localSecNode);
        securityMessageHeader.setRmtSecNodeId("105005");
        // 装填安全报文头成完整报文
        byte[] outSec =SecurityMessageHeaderUtils.marshal(securityMessageHeader,p_reqStr.getBytes("UTF-8"), true);
        WriteBankLogLn("服务地址：[" + bankFront.serverIP + ":" + bankFront.serverPort + "]。");
        StringBuilder sb = new StringBuilder();
        sb.append("POST / HTTP/1.1\r\n");
        sb.append("Host: " + bankFront.serverIP + ":" + bankFront.serverPort + "\r\n");
        sb.append("Server: BIP 1.0\r\n");
        sb.append("Date: "+Format.DateTimeFormat.format(new Date())+"\r\n");
        sb.append("Content-Type: application/octet-stream; charset=UTF-8\r\n");
        sb.append("Content-Length: " + outSec.length + "\r\n");
        sb.append("Connection: keep-alive\r\n");
        sb.append("\r\n");
        WriteBankLogLn("HTTP报文头："+sb);
        WriteBankLogLn2("发送的密文：\r\n" +new String(outSec));
        WriteBankLogLn("加密的报文内容:"+p_reqStr);
        WebRequest webReq = new WebRequest("http://"+bankFront.serverIP+":"+bankFront.serverPort);
        webReq.setRequestProperty("POST", "HTTP/1.1");
        webReq.setRequestProperty("Host", bankFront.serverIP + ":" + bankFront.serverPort);
        webReq.setRequestProperty("Server", "BIP 1.0");
        webReq.setRequestProperty("Date", Format.DateTimeFormat.format(new Date()));
        webReq.setRequestProperty("Content-Type", "application/octet-stream; charset=UTF-8");
        webReq.setRequestProperty("Connection", "keep-alive");
        String[] retStr = webReq.upload(outSec, getCharset());
        WriteBankLogStep3(retStr[1]);

        // 解析安全报文头及报文体
        Object[] recv = SecurityMessageHeaderUtils.ummarshal(retStr[1].getBytes(),
                true, new SecurityMessageHeader());
        byte[] responseData = (byte[]) recv[1];
        String str= new String(responseData,"UTF-8");
        WriteBankLogLn("获得明文报文体：" + str);
        return str;
    }
}
